package com.pl.config.security;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.session.jdbc.JdbcOperationsSessionRepository;
import org.springframework.session.security.SpringSessionBackedSessionRegistry;

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter{
	
	@Autowired
    MyAuthenctiationSuccessHandler myAuthenctiationSuccessHandler;
	
	@Autowired
    MyAuthenctiationFailureHandler myAuthenctiationFailureHandler;
	
	@Autowired
	private AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> authenticationDetailsSource;
	
	@Autowired
	private MyAuthenticationProvider myAuthenticationProvider;
	
	@Autowired
	private JdbcOperationsSessionRepository sessionRepository;
	
	@Bean
	public SpringSessionBackedSessionRegistry<?> mySessionRegistry() {
        return new SpringSessionBackedSessionRegistry<>(this.sessionRepository);
    }
	
	@Bean
	public PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}
	
	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//		auth.inMemoryAuthentication()
//			// 管理员，同事具有 ADMIN,USER权限，可以访问所有资源
//			.withUser("admin").password("$2a$10$86reeOWyB/K/grLDKtsBjOeU1nuODWOuyDfrtPi4xkEigR7lpJkkG").roles("ADMIN", "USER");
//			//.and()
//			// 普通用户，只能访问 /product/**
//		auth.inMemoryAuthentication().withUser("user").password("$2a$10$86reeOWyB/K/grLDKtsBjOeU1nuODWOuyDfrtPi4xkEigR7lpJkkG").roles("USER");
		
		// 设置自定义的userDetailsService
		//auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
		
		// 自定义认证
		auth.authenticationProvider(myAuthenticationProvider);
		//auth.eraseCredentials(true);
	}
	
	@Override
    public void configure(WebSecurity web) throws Exception {
        // 设置拦截忽略文件夹，可以对静态资源放行
        web.ignoring().antMatchers("/", "/css/**", "/images/**", "/js/**");
    }
	
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		//super.configure(http);
		http.csrf().disable();
		
		//定义哪些URL需要被保护、哪些不需要被保护
		http.authorizeRequests().antMatchers("/login/**").permitAll();
		
		//http.authorizeRequests().antMatchers("/oauth/authorize").denyAll();
		
		//注意这个有顺序
		http.authorizeRequests()
			//.antMatchers("/view/**").hasAnyRole("USER")
			//.antMatchers("/index/**").hasAnyRole("ADMIN")
			.antMatchers("/**").hasAnyRole("USER");
		
		//http.authorizeRequests().anyRequest().authenticated();
		
		//定义当需要用户登录时候，转到的登录页面
		http.formLogin()
			.successHandler(myAuthenctiationSuccessHandler)   //登录成功结果处理
			.failureHandler(myAuthenctiationFailureHandler)   //登录失败结果处理
			.loginPage("/login/loginPage")					  //登录页面
			.loginProcessingUrl("/login")
			//.defaultSuccessUrl("/index/index")
			// 指定authenticationDetailsSource
            .authenticationDetailsSource(authenticationDetailsSource)   //自定义表单
			.usernameParameter("userName")	//请求验证参数
			.passwordParameter("password");	//请求验证参数
		
		//默认登出url /logout
		http.logout().permitAll();
		
		//session失效后操作
		http.sessionManagement()
			.invalidSessionUrl("/login/loginPage")
			.maximumSessions(1).maxSessionsPreventsLogin(false)
			.sessionRegistry(mySessionRegistry())
			//.expiredSessionStrategy(new MySessionInformationExpiredStrategy());
			.expiredUrl("/login/loginPage");
		
		//http.addFilterBefore(new MySecurityContextPersistenceFilter(), SecurityContextPersistenceFilter.class);
		
		//ifarme 引入限制
		//X-Frame-Options: DENY     //表示该页面不允许在 frame 中展示，即便是在相同域名的页面中嵌套也不允许。。
		//X-Frame-Options: SAMEORIGIN    //表示该页面可以在相同域名页面的 frame 中展示。
		//X-Frame-Options: ALLOW-FROM http://caibaojian.com/   //表示该网页只能放在http://caibaojian.com//网页架设的iFrame内。
		http.headers().frameOptions().disable();
	}
	
}
